﻿using System;
using System.Diagnostics;
using System.Threading;
using SFML.Graphics;
using SFML.Window;
using Theta.Audio;
using Theta.Components;
using Theta.Input;
using Theta.Managers;

namespace Theta
{
    //Best place to save random shit I find is at the top of my Engine's main class!
    //ლ(ಠ益ಠლ Y U NO WORK THETA
    public static class Core
    {
        #region Private fields

        static RenderWindow _renderWindow;
        static AudioEngine _audioEngine;
        static ThetaGame _entryPoint;
        static Stopwatch _stopwatch;
        #endregion

        #region Properties
        
        public static Color ClearColor { get; set; }
        
        public static IntPtr WindowHandle
        {
            get { return RenderWindow.SystemHandle; }
        }

        public static AudioEngine Audio
        {
            get { return _audioEngine; }
        }

        public static bool IsOpened
        {
            get { return RenderWindow.IsOpened(); }
        }

        public static Vector2i WindowSize
        {
            get { return new Vector2i((int)RenderWindow.Width, (int)RenderWindow.Height); }
            set { _renderWindow.SetSize((uint)value.X, (uint)value.Y); }
        }

        public static View View
        {
            get { return RenderWindow.GetView(); }
            set { RenderWindow.SetView(value); }
        }

        public static RenderWindow RenderWindow
        {
            get { return _renderWindow; }
            private set { _renderWindow = value; }
        }
        //Exposes Input so components can use it
        public static InputManager Input
        {
            get { return _entryPoint.Input; }
        }

        public static ContentManager Content
        {
            get { return _entryPoint.Content; }
        }

        public static EntityList Entities
        {
            get { return _entryPoint.Entities; }
        }

        #endregion

        #region Constructor
        static Core()
        {
            _stopwatch = new Stopwatch();
            //Cornflower fucking Blue, what you gonna do?
            ClearColor = new Color(100, 149, 237);
        }
        #endregion

        #region Members

        public static void Initialize(ThetaGame entryPoint, VideoMode videoMode, string winTitle)
        {
            RenderWindow = new RenderWindow(videoMode, winTitle);
            InitCore(entryPoint);
        }

        public static void Initialize(ThetaGame entryPoint, VideoMode videoMode, string winTitle, Styles styles)
        {
            RenderWindow = new RenderWindow(videoMode, winTitle, styles);
            InitCore(entryPoint);
        }

        public static void Initialize(ThetaGame entryPoint, VideoMode videoMode, string winTitle, Styles styles, ContextSettings settings)
        {
            RenderWindow = new RenderWindow(videoMode, winTitle, styles, settings);
            InitCore(entryPoint);
        }

        internal static void InitCore(ThetaGame entryPoint)
        {
            RenderWindow.Closed += OnWindowClose;

            _entryPoint = entryPoint;
            _entryPoint.Initialize();

            while(RenderWindow.IsOpened())
            {
                _stopwatch.Stop();
                //Time elapsed since last update (Last loop, in the case)
                TimeSpan elapsedTime = _stopwatch.Elapsed;
                _stopwatch.Reset();
                _stopwatch.Start();

                RenderWindow.DispatchEvents();
                Update(elapsedTime);

                RenderWindow.Clear(ClearColor);
                Draw();

                RenderWindow.Display();
            }

            Dispose();
        }

        private static void Update(TimeSpan elapsedTime)
        {
            _entryPoint.Update(elapsedTime);
        }

        private static void Draw()
        {
            _entryPoint.Draw(RenderWindow);
        } 

        #endregion

        #region Events
        
        internal static void OnWindowClose(object sender, EventArgs a)
        {
            ((RenderWindow)sender).Close();
        }

        #endregion

        public static void Dispose()
        {
            _entryPoint.Dispose();
        }
    }
}
